#include <pthread.h>
#include <iostream>
using std::cout;
using std::endl;

class Singleton {
public:
    //静态成员函数只允许访问静态成员因为，静态成员函数没有this指针找不到非静态成员
    static Singleton* getInstance()
    {
        //当多个线程进去if语句
        //会造成Singleton对象被创建多个
        //最终只有一个对象的地址被_pInstance保存
        //其他对象就形成内存泄漏
        // if (_pInstance == nullptr)
        // {
        //     //第三种方法
        //     //先进行注册，在程序结束会自动调用destory
        //     atexit(destory);
        //     _pInstance = new Singleton(1, 2);
        // }

        //第一个参数传特定的参数，第二个参数传函数指针
        pthread_once( &once_control, init_r);
        return _pInstance;
    }
    
    void init(int x, int y)
    {
        _ix = x;
        _iy = y;
    }

    void print() const {
        cout << "(" << _ix
            << "," << _iy
            << ")" << endl;
    }
    friend class AutoRelease;
private:

    //如果将init_r设置为公有，我就可以使用域名多次调用它，每调用一次就会指向一个新的对象，前面的对象还没有销毁，缩回就会产生内存泄漏
    // 要将init_r设置为私有，这样只有类内可以调用，在类外不可以随意调用 
    static void init_r()
    {
        _pInstance = new Singleton(1, 2);
        //注册destory，程序结束自定调用destory
        atexit(destory);
    }

    //如果将destory定义为公有，那么我可以调用，销毁单例对象，如果我想再次使用单例对象，就不能使用了，因为pthread_once会限制只能
    //创建一个单例对象，所以将destory设置为私有
    static void destory()
    {
        if (_pInstance)
        {
            delete _pInstance;
            _pInstance = nullptr;
            cout << ">> delete heap" << endl;
        }
    }

    //单例模式将拷贝构造和赋值运算符重载函数删除掉
    Singleton(const Singleton& rhs) = delete;
    Singleton& operator= (const Singleton& rhs) = delete;
    //将构造函数设置为私有
    Singleton(int x, int y)
        :_ix(x)
        , _iy(y)
    {
        cout << "Singleton(int , int)" << endl;
    }
    //将析构函数设置为私有
    ~Singleton()
    {
        cout << "~Singleton()" << endl;
    }

    int _ix;
    int _iy;
    static Singleton* _pInstance;
    //因为上面为静态成员函数，所以这个参数也要初始化为静态参数
    static pthread_once_t once_control;
};
pthread_once_t Singleton::once_control = PTHREAD_ONCE_INIT;
//饱汉式（懒汉式）——懒加载
Singleton* Singleton::_pInstance = nullptr;

//饿汉式
//开始就将单例对象创建出来，即使程序中不使用这个单例对象
Singleton* Singleton::_pInstance = Singleton::getInstance();

class AutoRelease {
public:
    AutoRelease(Singleton* p)
        : _p(p)
    {
        cout << "AutoRelease(Singleton*)" << endl;
    }

    ~AutoRelease() {
        cout << "~AutoRelease()" << endl;
        if (_p) {
            //这里会报错是因为执行delete表达式会先调用析构函数回收对象申请的空间，然后再调用operator delete库函数回收本对象的空间
            //要想访问私有成员，必须声明为友元
            delete _p;
            _p = nullptr;
        }
    }
private:
    Singleton* _p;
};

void test0() {
    Singleton::getInstance()->init(1, 2);
    Singleton::getInstance()->print();
    // Singleton::destory();
    
    //下面两种情况都会double free
    //Singleton::destory();
    //AutoRelease ar2(Singleton::getInstance());
}
int main()
{
    test0();
    return 0;
}